#include "mainwindow.h"
#include <QWidget>
#include <QVBoxLayout>
#include <QStringList>
#include <QFileInfo>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setWindowTitle("Debug Tool for QProcess");
    setFixedSize(QSize(600, 350));
    QWidget *w = new QWidget();
    this->setCentralWidget(w);
    QVBoxLayout *layout = new QVBoxLayout();
    w->setLayout(layout);
    lineEdit = new QLineEdit();
    lineEdit->setPlaceholderText("Path of executable program...");
    layout->addWidget(lineEdit);
    btn = new QPushButton();
    btn->setText("Start");
    connect(btn, SIGNAL(clicked()), this, SLOT(clicked()));
    layout->addWidget(btn);

    plainLineEdit = new QPlainTextEdit();
    plainLineEdit->setReadOnly(true);
    plainLineEdit->setEnabled(false);
    plainLineEdit->setPlaceholderText("Debug steps:\n1. Set the path of executable program;\n2. Click the Start button.");
    layout->addWidget(plainLineEdit);

    process = new QProcess();
    process->terminate();

    connect(process, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(errorOccurred(QProcess::ProcessError)));
    connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus)));
    connect(process, SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()));
    connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()));
    connect(process, SIGNAL(started()), this, SLOT(started()));
    connect(process, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(stateChanged(QProcess::ProcessState)));



}

void MainWindow::showMessage(QString msg, QColor color)
{
    if(color == nullptr){
        plainLineEdit->appendPlainText(msg);
    }else{
        plainLineEdit->appendHtml(QString("<p style=\"color:%1\">%2</p>").arg(color.name(QColor::HexRgb)).arg(msg));
    }
}

void MainWindow::clicked()
{
    QString exePath = lineEdit->text().trimmed();
    if(exePath.isEmpty()){
        showMessage("Please set the path of executable program first!", QColor("#ff0000"));
        return;
    }

    if(btn->text() == "Start"){
        plainLineEdit->clear();
        QFileInfo exeFile(exePath);
        if(exeFile.isFile() && exeFile.isExecutable()){
            if(exePath.endsWith(".sh")){
                //process->start("/home/chan/OpenFOAM/chan-9/run/motorBike/test.sh", QStringList());
                process->setProgram("/bin/bash");
                process->setArguments(QStringList() << exePath);
                process->start();
            }else{
                process->setProgram(exePath);
                process->start();
            }
        }else{
            showMessage("The program should be an executable file!", QColor("#ff0000"));
            return;
        }

    }else{
        process->kill();
        btn->setText("Start");
    }
}


void MainWindow::errorOccurred(QProcess::ProcessError error)
{
    QString err;
    switch (error) {
    case 0:
    {
        err = "FailedToStart";
        break;
    }
    case 1:
    {
        err = "Crashed";
        break;
    }
    case 2:
    {
        err = "Timedout";
        break;
    }
    case 3:
    {
        err = "WriteError";
        break;
    }
    case 4:
    {
        err = "ReadError";
        break;
    }
    default:
    {
        err = "UnknownError";
        break;
    }
    }
    showMessage(QString("ErrorOccured[%1]: %2").arg(err).arg(process->errorString()), QColor("#ff0000"));
}

void MainWindow::finished(int exitCode, QProcess::ExitStatus exitStatus)
{
    QString status;
    switch (exitStatus) {
    case 1:
    {
        status = "CrashExit";
        break;
    }
    default:
    {
        status = "NormalExit";
        break;
    }
    }
    showMessage(QString("Finished[code=%1]: status = %2").arg(exitCode).arg(status), QColor("#00ff00"));
    btn->setText("Start");
}

void MainWindow::readyReadStandardError()
{
    QString str;
    showMessage(QString("ReadyReadStandardError: %1").arg(str.prepend(process->readAllStandardError())), QColor("#ff0000"));
}

void MainWindow::readyReadStandardOutput()
{
    QString str;
    showMessage(QString("ReadyReadStandardOutput: %1").arg(str.prepend(process->readAllStandardOutput())), QColor("#0000ff"));
}

void MainWindow::started()
{
    showMessage("Started!");
    btn->setText("Stop");
}

void MainWindow::stateChanged(QProcess::ProcessState newState)
{
    QString state;
    switch (newState) {
    case 1:
    {
        state = "Starting";
        break;
    }
    case 2:
    {
        state = "Running";
        break;
    }
    default:
    {
        state = "NotRunning";
        break;
    }
    }
    showMessage("State has changed to " + state, QColor("#ff00ff"));
}

